
package com.vito.framework.base.interceptor;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.vito.framework.base.annotation.*;
import com.vito.framework.cache.CacheKeys;
import com.vito.framework.cache.ICache;
import com.vito.framework.rest.bean.AppSession;
import com.vito.support.ApiResponse;
import com.vito.support.ResultEnum;
import com.vito.util.CookieUtil;
import com.vito.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/***************************************************************
 * Name: ApiInterceptor.java Create At: 2017年7月3日 Module: Description: [功能描述]
 * 拦截器
 *
 * @author zhaowentao
 *         修改历史 序号 日期 修改人 修改原因 1 2017年7月3日 ztshan 2
 ***************************************************************/
@Slf4j
public class ApiInterceptor implements HandlerInterceptor {

    @Autowired
    protected ICache cacheUtil;

    @Value("${adminPath}")
    private String adminPath = "/sys";
    @Value("${businessPath}")
    private String businessPath = "/o2o";
    @Value("${restPath}")
    private String restPath = "/api";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod method = (HandlerMethod) handler;

        ICache cacheUtil = (ICache) SpringUtil.getBean("cacheUtil");
        String uri = request.getRequestURI();

        String token = request.getHeader(CacheKeys.APP_TOKEN);
        if (StrUtil.isEmpty(token)) {
            token = CookieUtil.getCookieValue(request, CacheKeys.USER_TOKEN);
        }
        HttpSession session = request.getSession();
        if (session != null && !StrUtil.isEmpty(token)) {
            AppSession appSession = null;
            if (session.getAttribute(CacheKeys.APP_TOKEN + token) != null) {
                appSession = (AppSession) session.getAttribute(CacheKeys.APP_TOKEN + token);
            } else {
                appSession = cacheUtil.get(CacheKeys.APP_TOKEN + token);
                if (appSession != null) {
                    session.setAttribute(CacheKeys.APP_TOKEN + token, appSession);
                }
            }
            if (uri.lastIndexOf(adminPath + "/") >= 0) {
                //未登录后台系统
                if (appSession == null && uri.indexOf("/security/") < 0) {
                    outJsonStr(request, response, ApiResponse.of(ResultEnum.UNLOGIN));
                    return false;
                }
                return true;
            } else if (uri.lastIndexOf(businessPath + "/") >= 0) {
                //未登录商户系统
                if (appSession == null && uri.indexOf("/security/") < 0) {
                    outJsonStr(request, response, ApiResponse.of(ResultEnum.UNLOGIN));
                    return false;
                }
                return true;
            } else if (uri.lastIndexOf(restPath + "/") >= 0) {
                /**
                 * 分级权限
                 * AllowAll  访问无任何限制
                 * TokenAll  token有效 访问无任何限制
                 * AuthAll   token合法  微信用户授权可访问
                 * BindAll   token合法  微信用户授权并绑定手机可访问
                 * UserAll   绑定手机并身份认证后可以访问
                 * InnerAll  ip白名单内访问无限制
                 **/
                if (method.hasMethodAnnotation(AllowAll.class)) {//无任何限制

                    return true;
                } else if (method.hasMethodAnnotation(TokenAll.class)) {//token有效 才可以访问
                    if (appSession == null) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNCERTIFIED));
                        return false;
                    }
                } else if (method.hasMethodAnnotation(AuthAll.class)) {//需要授权才能访问
                    if (appSession == null) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNCERTIFIED));
                        return false;
                    } else if (StrUtil.isEmpty(appSession.getUnionId()) || StrUtil.isEmpty(appSession.getUserId())) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNAUTHORIZED));
                        return false;
                    }
                } else if (method.hasMethodAnnotation(UserAll.class)) {//有用于信息可以没有手机号
                    if (appSession == null) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNCERTIFIED));
                        return false;
                    } else if (StrUtil.isEmpty(appSession.getUnionId()) || StrUtil.isEmpty(appSession.getUserId())) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNAUTHORIZED));
                        return false;
                    } else if (StrUtil.isEmpty(appSession.getMemberId())) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNLOGIN));
                        return false;
                    }
                } else if (method.hasMethodAnnotation(BindAll.class)) {//需要授权并绑定手机才能访问
                    if (appSession == null) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNCERTIFIED));
                        return false;
                    } else if (StrUtil.isEmpty(appSession.getUnionId()) || StrUtil.isEmpty(appSession.getUserId())) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNAUTHORIZED));
                        return false;
                    } else if (StrUtil.isEmpty(appSession.getMobile()) || StrUtil.isEmpty(appSession.getMemberId())) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNBIND));
                        return false;
                    }
                }
                if (method.hasMethodAnnotation(LocationAll.class)) {//需要获取位置才能访问
                    if (appSession == null || appSession.getLongitude() == null || appSession.getLatitude() == null) {
                        outJsonStr(request, response, ApiResponse.of(ResultEnum.UNLOCATION));
                        return false;
                    }
                }
            }

        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }

    private void outJsonStr(HttpServletRequest request, HttpServletResponse response, ApiResponse result) {
        try {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Cache-Control", "no-cache");
            response.getWriter().write(JSON.toJSONString(result));
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }
}
